
char * empty_puzzle=".................................................................................";

extern t_128 cellsInBandBM[6] = { 
	{0x0000000007FFFFFF,0x0000000000000000}, //0 band 0 rows 123
	{0x003FFFFFF8000000,0x0000000000000000}, //1 band 1 rows 456 
	{0xFFC0000000000000,0x000000000001FFFF}, //2 band 2 rows 789
	{0x81C0E070381C0E07,0x0000000000000703}, //3 stack columns 123
	{0x0E070381C0E07038,0x000000000000381C}, //4 stack columns 456
	{0x70381C0E070381C0,0x000000000001C0E0}, //5 stack columns 789

};

extern t_128 cellsInHouseBM[27] = { 
	{0x00000000000001FF,0x0000000000000000}, //0 row1
	{0x000000000003FE00,0x0000000000000000}, //1
	{0x0000000007FC0000,0x0000000000000000}, //2
	{0x0000000FF8000000,0x0000000000000000}, //3
	{0x00001FF000000000,0x0000000000000000}, //4
	{0x003FE00000000000,0x0000000000000000}, //5
	{0x7FC0000000000000,0x0000000000000000}, //6
	{0x8000000000000000,0x00000000000000FF}, //7
	{0x0000000000000000,0x000000000001FF00}, //8
	{0x8040201008040201,0x0000000000000100}, //9 column 1
	{0x0080402010080402,0x0000000000000201}, //10
	{0x0100804020100804,0x0000000000000402}, //11
	{0x0201008040201008,0x0000000000000804}, //12
	{0x0402010080402010,0x0000000000001008}, //13
	{0x0804020100804020,0x0000000000002010}, //14
	{0x1008040201008040,0x0000000000004020}, //15
	{0x2010080402010080,0x0000000000008040}, //16
	{0x4020100804020100,0x0000000000010080}, //17
	{0x00000000001C0E07,0x0000000000000000}, //18 box 1
	{0x0000000000E07038,0x0000000000000000}, //19
	{0x00000000070381C0,0x0000000000000000}, //20
	{0x0000E07038000000,0x0000000000000000}, //21
	{0x00070381C0000000,0x0000000000000000}, //22
	{0x00381C0E00000000,0x0000000000000000}, //23
	{0x81C0000000000000,0x0000000000000703}, //24
	{0x0E00000000000000,0x000000000000381C}, //25
	{0x7000000000000000,0x000000000001C0E0}, //26
};
//The cell indexes in each of the 9 rows, 9 columns, and 9 squares out of fss
byte cellsInGroup[27][9] =
{
	{ 0, 1, 2, 3, 4, 5, 6, 7, 8},{ 9,10,11,12,13,14,15,16,17},{18,19,20,21,22,23,24,25,26},
	{27,28,29,30,31,32,33,34,35},{36,37,38,39,40,41,42,43,44},{45,46,47,48,49,50,51,52,53},
	{54,55,56,57,58,59,60,61,62},{63,64,65,66,67,68,69,70,71},{72,73,74,75,76,77,78,79,80},
	{ 0, 9,18,27,36,45,54,63,72},{ 1,10,19,28,37,46,55,64,73},{ 2,11,20,29,38,47,56,65,74},
	{ 3,12,21,30,39,48,57,66,75},{ 4,13,22,31,40,49,58,67,76},{ 5,14,23,32,41,50,59,68,77},
	{ 6,15,24,33,42,51,60,69,78},{ 7,16,25,34,43,52,61,70,79},{ 8,17,26,35,44,53,62,71,80},
	{ 0, 1, 2, 9,10,11,18,19,20},{ 3, 4, 5,12,13,14,21,22,23},{ 6, 7, 8,15,16,17,24,25,26},
	{27,28,29,36,37,38,45,46,47},{30,31,32,39,40,41,48,49,50},{33,34,35,42,43,44,51,52,53},
	{54,55,56,63,64,65,72,73,74},{57,58,59,66,67,68,75,76,77},{60,61,62,69,70,71,78,79,80}
};




//! Table containing the fix data for the 81 cells
CELL_FIX cellsFixedData[81] = {
{ 0, 0, 0, 9, 0,18, 0, "r1c1",{0x80402010081C0FFE,0x0000000000000100}}, //0
{ 1, 0, 1,10, 0,18, 1, "r1c2",{0x00804020101C0FFD,0x0000000000000201}}, //1
{ 2, 0, 2,11, 0,18, 2, "r1c3",{0x01008040201C0FFB,0x0000000000000402}}, //2
{ 3, 0, 3,12, 1,19, 0, "r1c4",{0x0201008040E071F7,0x0000000000000804}}, //3
{ 4, 0, 4,13, 1,19, 1, "r1c5",{0x0402010080E071EF,0x0000000000001008}}, //4
{ 5, 0, 5,14, 1,19, 2, "r1c6",{0x0804020100E071DF,0x0000000000002010}}, //5
{ 6, 0, 6,15, 2,20, 0, "r1c7",{0x10080402070381BF,0x0000000000004020}}, //6
{ 7, 0, 7,16, 2,20, 1, "r1c8",{0x201008040703817F,0x0000000000008040}}, //7
{ 8, 0, 8,17, 2,20, 2, "r1c9",{0x40201008070380FF,0x0000000000010080}}, //8
{ 9, 1, 0, 9, 0,18, 3, "r2c1",{0x80402010081FFC07,0x0000000000000100}}, //9
{10, 1, 1,10, 0,18, 4, "r2c2",{0x00804020101FFA07,0x0000000000000201}}, //10
{11, 1, 2,11, 0,18, 5, "r2c3",{0x01008040201FF607,0x0000000000000402}}, //11
{12, 1, 3,12, 1,19, 3, "r2c4",{0x0201008040E3EE38,0x0000000000000804}}, //12
{13, 1, 4,13, 1,19, 4, "r2c5",{0x0402010080E3DE38,0x0000000000001008}}, //13
{14, 1, 5,14, 1,19, 5, "r2c6",{0x0804020100E3BE38,0x0000000000002010}}, //14
{15, 1, 6,15, 2,20, 3, "r2c7",{0x1008040207037FC0,0x0000000000004020}}, //15
{16, 1, 7,16, 2,20, 4, "r2c8",{0x201008040702FFC0,0x0000000000008040}}, //16
{17, 1, 8,17, 2,20, 5, "r2c9",{0x402010080701FFC0,0x0000000000010080}}, //17
{18, 2, 0, 9, 0,18, 6, "r3c1",{0x804020100FF80E07,0x0000000000000100}}, //18
{19, 2, 1,10, 0,18, 7, "r3c2",{0x0080402017F40E07,0x0000000000000201}}, //19
{20, 2, 2,11, 0,18, 8, "r3c3",{0x0100804027EC0E07,0x0000000000000402}}, //20
{21, 2, 3,12, 1,19, 6, "r3c4",{0x0201008047DC7038,0x0000000000000804}}, //21
{22, 2, 4,13, 1,19, 7, "r3c5",{0x0402010087BC7038,0x0000000000001008}}, //22
{23, 2, 5,14, 1,19, 8, "r3c6",{0x08040201077C7038,0x0000000000002010}}, //23
{24, 2, 6,15, 2,20, 6, "r3c7",{0x1008040206FF81C0,0x0000000000004020}}, //24
{25, 2, 7,16, 2,20, 7, "r3c8",{0x2010080405FF81C0,0x0000000000008040}}, //25
{26, 2, 8,17, 2,20, 8, "r3c9",{0x4020100803FF81C0,0x0000000000010080}}, //26
{27, 3, 0, 9, 3,21, 0, "r4c1",{0x8040E07FF0040201,0x0000000000000100}}, //27
{28, 3, 1,10, 3,21, 1, "r4c2",{0x0080E07FE8080402,0x0000000000000201}}, //28
{29, 3, 2,11, 3,21, 2, "r4c3",{0x0100E07FD8100804,0x0000000000000402}}, //29
{30, 3, 3,12, 4,22, 0, "r4c4",{0x0207038FB8201008,0x0000000000000804}}, //30
{31, 3, 4,13, 4,22, 1, "r4c5",{0x0407038F78402010,0x0000000000001008}}, //31
{32, 3, 5,14, 4,22, 2, "r4c6",{0x0807038EF8804020,0x0000000000002010}}, //32
{33, 3, 6,15, 5,23, 0, "r4c7",{0x10381C0DF9008040,0x0000000000004020}}, //33
{34, 3, 7,16, 5,23, 1, "r4c8",{0x20381C0BFA010080,0x0000000000008040}}, //34
{35, 3, 8,17, 5,23, 2, "r4c9",{0x40381C07FC020100,0x0000000000010080}}, //35
{36, 4, 0, 9, 3,21, 3, "r5c1",{0x8040FFE038040201,0x0000000000000100}}, //36
{37, 4, 1,10, 3,21, 4, "r5c2",{0x0080FFD038080402,0x0000000000000201}}, //37
{38, 4, 2,11, 3,21, 5, "r5c3",{0x0100FFB038100804,0x0000000000000402}}, //38
{39, 4, 3,12, 4,22, 3, "r5c4",{0x02071F71C0201008,0x0000000000000804}}, //39
{40, 4, 4,13, 4,22, 4, "r5c5",{0x04071EF1C0402010,0x0000000000001008}}, //40
{41, 4, 5,14, 4,22, 5, "r5c6",{0x08071DF1C0804020,0x0000000000002010}}, //41
{42, 4, 6,15, 5,23, 3, "r5c7",{0x10381BFE01008040,0x0000000000004020}}, //42
{43, 4, 7,16, 5,23, 4, "r5c8",{0x203817FE02010080,0x0000000000008040}}, //43
{44, 4, 8,17, 5,23, 5, "r5c9",{0x40380FFE04020100,0x0000000000010080}}, //44
{45, 5, 0, 9, 3,21, 6, "r6c1",{0x807FC07038040201,0x0000000000000100}}, //45
{46, 5, 1,10, 3,21, 7, "r6c2",{0x00BFA07038080402,0x0000000000000201}}, //46
{47, 5, 2,11, 3,21, 8, "r6c3",{0x013F607038100804,0x0000000000000402}}, //47
{48, 5, 3,12, 4,22, 6, "r6c4",{0x023EE381C0201008,0x0000000000000804}}, //48
{49, 5, 4,13, 4,22, 7, "r6c5",{0x043DE381C0402010,0x0000000000001008}}, //49
{50, 5, 5,14, 4,22, 8, "r6c6",{0x083BE381C0804020,0x0000000000002010}}, //50
{51, 5, 6,15, 5,23, 6, "r6c7",{0x1037FC0E01008040,0x0000000000004020}}, //51
{52, 5, 7,16, 5,23, 7, "r6c8",{0x202FFC0E02010080,0x0000000000008040}}, //52
{53, 5, 8,17, 5,23, 8, "r6c9",{0x401FFC0E04020100,0x0000000000010080}}, //53
{54, 6, 0, 9, 6,24, 0, "r7c1",{0xFF80201008040201,0x0000000000000703}}, //54
{55, 6, 1,10, 6,24, 1, "r7c2",{0xFF40402010080402,0x0000000000000703}}, //55
{56, 6, 2,11, 6,24, 2, "r7c3",{0xFEC0804020100804,0x0000000000000703}}, //56
{57, 6, 3,12, 7,25, 0, "r7c4",{0x7DC1008040201008,0x000000000000381C}}, //57
{58, 6, 4,13, 7,25, 1, "r7c5",{0x7BC2010080402010,0x000000000000381C}}, //58
{59, 6, 5,14, 7,25, 2, "r7c6",{0x77C4020100804020,0x000000000000381C}}, //59
{60, 6, 6,15, 8,26, 0, "r7c7",{0x6FC8040201008040,0x000000000001C0E0}}, //60
{61, 6, 7,16, 8,26, 1, "r7c8",{0x5FD0080402010080,0x000000000001C0E0}}, //61
{62, 6, 8,17, 8,26, 2, "r7c9",{0x3FE0100804020100,0x000000000001C0E0}}, //62
{63, 7, 0, 9, 6,24, 3, "r8c1",{0x01C0201008040201,0x00000000000007FF}}, //63
{64, 7, 1,10, 6,24, 4, "r8c2",{0x81C0402010080402,0x00000000000007FE}}, //64
{65, 7, 2,11, 6,24, 5, "r8c3",{0x81C0804020100804,0x00000000000007FD}}, //65
{66, 7, 3,12, 7,25, 3, "r8c4",{0x8E01008040201008,0x00000000000038FB}}, //66
{67, 7, 4,13, 7,25, 4, "r8c5",{0x8E02010080402010,0x00000000000038F7}}, //67
{68, 7, 5,14, 7,25, 5, "r8c6",{0x8E04020100804020,0x00000000000038EF}}, //68
{69, 7, 6,15, 8,26, 3, "r8c7",{0xF008040201008040,0x000000000001C0DF}}, //69
{70, 7, 7,16, 8,26, 4, "r8c8",{0xF010080402010080,0x000000000001C0BF}}, //70
{71, 7, 8,17, 8,26, 5, "r8c9",{0xF020100804020100,0x000000000001C07F}}, //71
{72, 8, 0, 9, 6,24, 6, "r9c1",{0x81C0201008040201,0x000000000001FE03}}, //72
{73, 8, 1,10, 6,24, 7, "r9c2",{0x81C0402010080402,0x000000000001FD03}}, //73
{74, 8, 2,11, 6,24, 8, "r9c3",{0x81C0804020100804,0x000000000001FB03}}, //74
{75, 8, 3,12, 7,25, 6, "r9c4",{0x0E01008040201008,0x000000000001F71C}}, //75
{76, 8, 4,13, 7,25, 7, "r9c5",{0x0E02010080402010,0x000000000001EF1C}}, //76
{77, 8, 5,14, 7,25, 8, "r9c6",{0x0E04020100804020,0x000000000001DF1C}}, //77
{78, 8, 6,15, 8,26, 6, "r9c7",{0x7008040201008040,0x000000000001BFE0}}, //78
{79, 8, 7,16, 8,26, 7, "r9c8",{0x7010080402010080,0x0000000000017FE0}}, //79
{80, 8, 8,17, 8,26, 8, "r9c9",{0x7020100804020100,0x000000000000FFE0}}, //80
};


byte miniline[54][3] =
{	{ 0, 1, 2},{ 3, 4, 5},{ 6, 7, 8},{ 9,10,11},{12,13,14},{15,16,17},{18,19,20},{21,22,23},{24,25,26},
	{27,28,29},{30,31,32},{33,34,35},{36,37,38},{39,40,41},{42,43,44},{45,46,47},{48,49,50},{51,52,53},
	{54,55,56},{57,58,59},{60,61,62},{63,64,65},{66,67,68},{69,70,71},{72,73,74},{75,76,77},{78,79,80},
	{ 0, 9,18},{27,36,45},{54,63,72},{ 1,10,19},{28,37,46},{55,64,73},{ 2,11,20},{29,38,47},{56,65,74},
	{ 3,12,21},{30,39,48},{57,66,75},{ 4,13,22},{31,40,49},{58,67,76},{ 5,14,23},{32,41,50},{59,68,77},
	{ 6,15,24},{33,42,51},{60,69,78},{ 7,16,25},{34,43,52},{61,70,79},	{ 8,17,26},{35,44,53},{62,71,80}
};

// computed table unit  1_18 &   box 18_27 (3 per unit)
t_128 minilineBM[54] =
{	{0x7,0},{0x38,0},{0x1C0,0}, //0 row1
  	{0xE00,0}, {0x7000,0},{0x38000,0},//1
  	{0x1C0000,0},{0xE00000,0}, {0x7000000,0},//2
  	{0x38000000,0},{0x1C0000000,0},{0xE00000000,0}, //3
  	{0x7000000000,0},{0x38000000000,0},{0x1C0000000000,0}, //4
    {0xE00000000000,0},{0x7000000000000,0},{0x38000000000000,0}, //5
  	{0x1C0000000000000,0},{0xE00000000000000,0},{0x7000000000000000,0}, //6
  	{0x8000000000000000,0x3},{0,0x1c},{0,0xE0}, //7
  	{0,0x700},{0,0x3800},{0,0x1C000},//8
  	{  0x40201,0},  {0x201008000000,0}, {0x8040000000000000,0x100},//9 column 1
    {  0x80402,0},  {0x402010000000,0}, {0x0080000000000000,0x201},//10
 	{ 0x100804,0},  {0x804020000000,0}, {0x0100000000000000,0x402},//11
    { 0x201008,0}, {0x1008040000000,0}, {0x0200000000000000,0x804}, //12
	{ 0x402010,0}, {0x2010080000000,0}, {0x0400000000000000,0x1008}, //13
	{ 0x804020,0}, {0x4020100000000,0}, {0x0800000000000000,0x2010}, //14
	{0x1008040,0}, {0x8040200000000,0}, {0x1000000000000000,0x4020}, //15
	{0x2010080,0},{0x10080400000000,0}, {0x2000000000000000,0x8040}, //16
	{0x4020100,0},{0x20100800000000,0}, {0x4000000000000000,0x10080}, //17 
};
 


/* tables used in symmetry processing
   [36][2] sd1_36  diagonal  sd2_36 diag 2   sst_36 stick
   sc_40[40][2] central   sr90_20[20][4] rot 90
   sym_81[5][81] direct sym   d1  d2 st cc r90
   sym_f9[3][9] fix positions  d1 d2 stick

*/

USHORT perms_band[6][3]={0,1,2,0,2,1,1,0,2,// band order
                        1,2,0,2,0,1,2,1,0};  // all perms

USHORT sh_36[36][2]={
0 , 72, 1 , 73, 2 , 74, 3 , 75,4,76,5,77,6,78,7,79,8,80,  // 9
9 , 63,10,64,11,65,12,66,13,67,14,68,15,69,16,70,17,71,  // 18
18,54,19,55,20,56,21,57,22,58,23,59,24,60,25,61,26,62, //27
27,45,28,46,29,47,30,48,31,49,32,50,33,51,34,52,35,53 // 36
};

USHORT sv_36[36][2]={  // only searched as direct
0,8, 1,7, 2,6, 3,5,  // 4
9,17, 10,16, 11,15, 12,14,  // 8
18,26, 19,25, 20,24, 21,23,  // 12
27,35, 28,34, 29,33, 30,32,  // 16
36,44, 37,43, 38,42, 39,41,  // 20
45,53, 46,52, 47,51, 48,50,  // 24
54,62, 55,61, 56,60, 57,59,  // 28
63,71, 64,70, 65,69, 66,68,  // 32
72,80, 73,79, 74,78, 75,77  // 36
};

USHORT sd1_36[36][2]={
31,39, 32,48, 41,49, // box 5
1,9, 2,18, 3,27, 4,36, 5,45, // band1 stack 1 
11,19, 12,28, 13,37, 14,46, 
21,29, 22,38, 23,47, 
6,54, 7,63, 8,72, 15,55,16,64, 17,73, 
24,56, 25,65, 26,74,  
33,57, 34,66, 35,75, 42,58, 43,67, 44,76, 
51,59, 52,68, 53,77, 61,69, 62,78, 71,79   
};
USHORT sd2_36[36][2]={ // only searched as direct
7 , 17, 6 , 26, 5 , 35, 4 , 44,  // 4
3 , 53, 2 , 62, 1 , 71, 0 , 80,  // 8
15 , 25, 14 , 34, 13 , 43, 12 , 52,  // 12
11 , 61, 10, 70, 9 , 79, 23 , 33,  // 16
22 , 42, 21 , 51, 20 , 60, 19 , 69,  // 20
18 , 78, 31 , 41, 30 , 50, 29 , 59,  // 24
28 , 68, 27 , 77, 39 , 49, 38 , 58,  // 28
37 , 67, 36 , 76, 47 , 57, 46 , 66,  // 32
45 , 75, 55 , 65, 54 , 74, 63 , 73  // 36
};
USHORT sst_36[36][2]={
27,29, 36,38, 45,47,// Box4 and stack 1
1 ,55, 10,64, 19,73 , 0,56, 2,54, 9,65, 11,63, 18,74, 20,72,
30 , 32, 39 ,  41,48 , 50, //box 5 stack 2
4,58, 13,67, 22,76, 3,59, 12,68, 21,77, 5,57, 14,66, 23,75,
33,35, 42,44, 51,53,  //box 6 stack 3
7,61, 16,70, 25,79, 6,62, 15,71, 24,80, 8,60, 17,69, 26,78
};
USHORT sc_40[40][2]={
80 , 0, 79 , 1, 78 , 2, 77 , 3,  //4
76 , 4, 75 , 5, 74 , 6, 73 , 7,  //8
72 , 8, 71 , 9, 70 , 10, 69 , 11,  //12
68 , 12, 67 , 13, 66 , 14, 65 , 15,  //16
64 , 16, 63 , 17, 62 , 18, 61 , 19,  //20
60 , 20, 59 , 21, 58 , 22, 57 , 23,  //24
56 , 24, 55 , 25, 54 , 26, 53 , 27,  //28
52 , 28, 51 , 29, 50 , 30, 49 , 31,  //32
48 , 32, 47 , 33, 46 , 34, 45 , 35,  //36
44 , 36, 43 , 37, 42 , 38, 41 , 39  //40
};
USHORT sr90_20[20][4]={
0 , 8, 80 , 72, 1 , 17, 79 , 63, 2 , 26, 78 , 54, 3 , 35, 77 , 45,  // 4
4 , 44, 76 , 36, 9 , 7, 71 , 73, 10 , 16, 70 , 64, 11 , 25, 69 , 55,  // 8
12 , 34, 68 , 46, 13 , 43, 67 , 37, 18 , 6, 62 , 74, 19 , 15, 61 , 65,  // 12
20 , 24, 60 , 56, 21 , 33, 59 , 47, 22 , 42, 58 , 38, 27 , 5, 53 , 75,  // 16
28 , 14, 52 , 66, 29 , 23, 51 , 57, 30 , 32, 50 , 48, 31 , 41, 49 , 39  // 20
};
USHORT sym_81[5][81]={    // d1  d2  st  c  r90
0 , 9 , 18 , 27 , 36 , 45 , 54 , 63 , 72 , 1 , 10 , 19 , 28 , 37 , 46 , 55 , 64 , 73 , 2 , 11 , 
20 , 29 , 38 , 47 , 56 , 65 , 74 , 3 , 12 , 21 , 30 , 39 , 48 , 57 , 66 , 75 , 4 , 13 , 22 , 31 , 
40 , 49 , 58 , 67 , 76 , 5 , 14 , 23 , 32 , 41 , 50 , 59 , 68 , 77 , 6 , 15 , 24 , 33 , 42 , 51 , 
60 , 69 , 78 , 7 , 16 , 25 , 34 , 43 , 52 , 61 , 70 , 79 , 8 , 17 , 26 , 35 , 44 , 53 , 62 , 71 , 80 ,  // d1
80 , 71 , 62 , 53 , 44 , 35 , 26 , 17 , 8 , 79 , 70 , 61 , 52 , 43 , 34 , 25 , 16 , 7 , 78 , 69 , 
60 , 51 , 42 , 33 , 24 , 15 , 6 , 77 , 68 , 59 , 50 , 41 , 32 , 23 , 14 , 5 , 76 , 67 , 58 , 49 , 
40 , 31 , 22 , 13 , 4 , 75 , 66 , 57 , 48 , 39 , 30 , 21 , 12 , 3 , 74 , 65 , 56 , 47 , 38 , 29 , 
20 , 11 , 2 , 73 , 64 , 55 , 46 , 37 , 28 , 19 , 10 , 1 , 72 , 63 , 54 , 45 , 36 , 27 , 18 , 9 , 0 ,  // d2
56 , 55 , 54 , 59 , 58 , 57 , 62 , 61 , 60 , 65 , 64 , 63 , 68 , 67 , 66 , 71 , 70 , 69 , 74 , 73 , 
72 , 77 , 76 , 75 , 80 , 79 , 78 , 29 , 28 , 27 , 32 , 31 , 30 , 35 , 34 , 33 , 38 , 37 , 36 , 41 , 
40 , 39 , 44 , 43 , 42 , 47 , 46 , 45 , 50 , 49 , 48 , 53 , 52 , 51 , 2 , 1 , 0 , 5 , 4 , 3 , 
8 , 7 , 6 , 11 , 10 , 9 , 14 , 13 , 12 , 17 , 16 , 15 , 20 , 19 , 18 , 23 , 22 , 21 , 26 , 25 , 24 ,  //st
80 , 79 , 78 , 77 , 76 , 75 , 74 , 73 , 72 , 71 , 70 , 69 , 68 , 67 , 66 , 65 , 64 , 63 , 62 , 61 , 
60 , 59 , 58 , 57 , 56 , 55 , 54 , 53 , 52 , 51 , 50 , 49 , 48 , 47 , 46 , 45 , 44 , 43 , 42 , 41 , 
40 , 39 , 38 , 37 , 36 , 35 , 34 , 33 , 32 , 31 , 30 , 29 , 28 , 27 , 26 , 25 , 24 , 23 , 22 , 21 , 
20 , 19 , 18 , 17 , 16 , 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ,  // c
8 , 17 , 26 , 35 , 44 , 53 , 62 , 71 , 80 , 7 , 16 , 25 , 34 , 43 , 52 , 61 , 70 , 79 , 6 , 15 , 
24 , 33 , 42 , 51 , 60 , 69 , 78 , 5 , 14 , 23 , 32 , 41 , 50 , 59 , 68 , 77 , 4 , 13 , 22 , 31 , 
40 , 49 , 58 , 67 , 76 , 3 , 12 , 21 , 30 , 39 , 48 , 57 , 66 , 75 , 2 , 11 , 20 , 29 , 38 , 47 , 
56 , 65 , 74 , 1 , 10 , 19 , 28 , 37 , 46 , 55 , 64 , 73 , 0 , 9 , 18 , 27 , 36 , 45 , 54 , 63 , 72  }; // r90


USHORT sym_f9[3][9] ={  // d1 d2 st
0 , 10 , 20 , 30 , 40 , 50 , 60 , 70 , 80 ,  // d1
8 , 16 , 24 , 32 , 40 , 48 , 56 , 64 , 72 ,  // d2
28 , 31 , 34 , 37 , 40 , 43 , 46 , 49 , 52   // st
};

USHORT  sym_tcor[3][9]={
	0,2,1,4,3,6,5,8,7,   // central
    0,1,2,4,3,6,5,8,7,   // 3 fix
	0,2,3,4,1,6,7,8,5,   // r90
	};  



USHORT skloop_boxes_table[15][6]= // 4 boxes in square
      {{0,1,4,3,0,0},     {0,1,7,6,0,0},	     {3,4,7,6,0,0},
	  {0,2,5,3,0,0},      {0,2,8,6,0,0},	     {3,5,8,6,0,0},
	  {1,2,5,4,0,0},      {1,2,8,7,0,0},		 {4,5,8,7,0,0}, 
	      // 6 boxes
      {0,1,4,5,8,6},     {0,1,7,8,5,3},         {0,2,5,4,7,6},
      {0,2,8,7,4,3},     {1,2,5,3,6,7},         {1,2,8,6,3,4}	};

USHORT skloop_sub_table[9][4]= {// relative row,col in box
	{1,2,3,6},     {0,2,4,7},   {0,1,5,8},			// empty row1
	{4,5,0,6},	   {3,5,1,7},   {3,4,2,8},			// empty row2
	{7,8,0,3},	   {6,8,1,4},   {6,7,2,5}  };		// empty row 3
USHORT mask9_row_col [6]={0x0007,0x0038,0x01C0,
	                      0x0049,0x0092,0x0124};
USHORT cross_relative_box1[3]={0x0038,0x0007,0x0007};
USHORT cross_relative_box2[3]={0x01C0,0x01C0,0x0038};
USHORT cross_relative_outband[3]={0x0038+0x01C0,0x0007+0x01C0,0x0007+0x0038};


COMB9 tcomb9[9+36+84+126] [2];
int indtcomb9[5]={0,9,9+36,9+36+84,129+126};
USHORT indtcomb9rev[512];


class GEN_TABLES{
public:
	GEN_TABLES(){ 
	//============== 
	COMBINE combi; 
	USHORT  trc[9]={8,7,6,5,4,3,2,1,0},trc_s[9];
	int n=-1;
	for(int i=0;i<512;i++) indtcomb9rev[i]=0;
	for(int i=1,i2=8;i<5;i++,i2--){
		combi.First(9,i,trc,trc_s); // build the r/c lot3 tables
		while(++n ) { 
			COMB9 * tc9=tcomb9[n];
			tc9[0].bm.f=tc9[1].bm.f=0;
			for(int j=0;j<9;j++){
				if(j<i2) tc9[1].bm.Set(trc_s[j]);
				else   tc9[0].bm.Set(trc_s[j]);		// smallest in 0		
			}
			tc9[0].nt=tc9[0].bm.String(tc9[0].t);
			tc9[1].nt=tc9[1].bm.String(tc9[1].t);
			indtcomb9rev[tc9[0].bm.f]=n;
			indtcomb9rev[tc9[1].bm.f]=n+(1<<11);
			if(!combi.Next()) break; 	 
		}
	}
		Genbase(); 	Gen2();	Gen3(); Gen4();
	}
	void Genbase();
	void Gen2();
	void Gen3();
	void Gen4();

}gen_tables;


// tables generated in the below constructor
int TblMult3[9];  // 3*i
int TblMult9[9];  // 9*i
int TblOtherMask9[9] ; // clear digit in three lines in the column of a block
int Tbldiv3[27]; //i/3 eg :  mini row or digit in F
byte Tblmod3[27];  // i%3
int TblMod9[81]; //i%9 eg : column in block or cell to column
int Tblstartblock[27]; // block offset to first cell
int Tblofftorow[27];// i/9 relative row within a block  (offset to row)
int Tblofftobox[27];//(i%9)/3offset to box
// other bands for a F[i]
byte TblAnother1[27];
byte TblAnother2[27];
int TblBoard_BlockMask27[27]; //1<<i 
int TblRowMask[8];// rows where single  found  000 to 111
word TblShrinkUnsolved[8]; // only unsolved rows
int TblMask26row[9];
void GEN_TABLES::Genbase(){
	for(int i=0;i<9;i++){
		TblMult3[i] = 3*i;
		TblMult9[i] = 9*i ;
		TblOtherMask9[i]=((1<<i) * Zhoucol) ^ BIT_SET_30;
	}
	for(int i=0;i<27;i++){
		Tbldiv3[i] = i/3;
		Tblmod3[i] = i%3;
		TblMod9[i] = TblMod9[i+27] = TblMod9[i+54] = i%9;
		Tblstartblock[i] = (i%3)*27;
		Tblofftorow[i] = i/9;
		Tblofftobox[i] = (i%9)/3;
		TblAnother1[i]=(i%3)? 3*( i/3 ) :3*( i/3 )+1;
		TblAnother2[i]=(i%3 - 2)?3*( i/3 )+2 :3*( i/3 )+1;
		TblBoard_BlockMask27[i] = (1<<i);
	}
	for(int i=0;i<8;i++){ // bits 25_27  0 to 7
		int rmask=0;  // rows where a single is found
		if(i&1) rmask |= 0x1FF;
		if(i&2) rmask |= (0x1FF<<9);
		if(i&4) rmask |= (0x1FF<<18);
		TblRowMask[i]=rmask ^  BIT_SET_27;

		int rshr=0; // in pointing claiming killl shrinked defined
		if(i&1) rshr |= 7;
		if(i&2) rshr |= (7<<3);
		if(i&4) rshr |= (7<<6);
		TblShrinkUnsolved[i] = rshr;
	}


	for(int i=0;i<9;i++){ // i is the minirow order 0_8
		int w=0x1ff ^ (7<<3*(i%3)); //to kill in the row
		TblMask26row[i]=  (w<<(9*(i/3))) ^ BIT_SET_30;

	}

}

byte Tbloffset[81]; // giving cell to offset in a band
byte TblBoard_Block[81]; // giving cell -> band 

byte TblCelltoBox[81];// relative position in the box
//byte TblaffectedCells[81][20]; // all cells controlled by cell i
byte TblOtherSameBand[27][8]; // cleaning cells other digits

byte BitCount[512] ; // number of bits in a 9 bits value
byte TblBitToInd[512] ; // value 1 to 9 for 1<<n 
byte TblBitIndex[257] ; // value 0 to 8 for 1<<n 
byte Tblfirst0_8[512]; // lowest bit set to 1  bits 1_9
byte TblShrinkMask[512] ;// existing minirows 000 to 111

void GEN_TABLES::Gen2(){
	for(int i=0;i<81;i++){
		Tbloffset[i]=i%27;
		TblBoard_Block[i] =i/27;
		TblCelltoBox[i]=3*((i%27)/9) +i%3 ;
	}

	byte *p=TblOtherSameBand[0];
	for(int i=0;i<27;i++){
		int digit=i/3,blk=i%3;
		for(int j=0;j<9;j++)if(j-digit) (*p++) = (3*j+blk) ;
	}

	for(int i=0;i<512;i++){
		int n=0,po=0;
		for(int j=8;j>=0;j--) if(i &(1<<j)){
			n++; po=j;
		}
		int bti= (n==1)? po+1:0;
		TblBitToInd[i]= bti;
		Tblfirst0_8[i] = po;
		BitCount[i] = n;
		int sh=0;
		if(i& 7) sh+=1;
		if(i&(7<<3)) sh+=2;
		if(i&(7<<6)) sh+=4;
		TblShrinkMask[i] = sh;
	}
	for(int i=0;i<256;i++) TblBitIndex[i]=0;
	for(int i=1;i<9;i++) TblBitIndex[1<<i]=i;
}

int TblComplexMask[512]; // keep mini rows still valid optimised process
int TblKillMask[512]; // killed candidates pointing general
word TblComplexShort[512];  // same as complex  minirows still valid
word TblComplexShortBox[512];
//int TblUniqFlag[8] = {1,1,1,0,1,0,0,0};
word TblNewBoxRow[512]; // new minirow alone in box after shrink
byte TblRowUniq[512] ; // 1 is row not defined in block  mode  to 111
word TblColumnSingleinBox[512];
word TblColumnSingle[512]; // single in column applied to shrinked bloc
word TblShrinkSingle[512] ; // keep only rows with single
int TblMaskSingle[512]; // kill in other blocks locked column /box
int TblMaskDouble[512];// kill for locked in box / column

/*	 7 000 000    9 mini row sequence 
       E00 000    8
	   1C0 000    7
	    38 000    6
	     7 000    5
	       E00    4
	       1C0    3
	        38    2
	         7    1  */
void GEN_TABLES::Gen3(){
	for(int i=0;i<512;i++){
		// pointing claiming in band kill9 initial = already killed
		int shsh=0,kill=0,aigkill=0,ctlrb=0,kill9= i ^  0x1ff,killd=kill9;
		for(int ib=0;ib<3;ib++){ // first locked in boxes
			int iw=i & (0x49<<ib); // shrinked box 1  1..1..1
			if(!BitCount[iw]) {aigkill=1;break;}
			if(BitCount[iw] == 1){
				int imini=Tblfirst0_8[iw],ir=imini/3;
				shsh |= (1<<imini);
				for(int ib2=0;ib2<3;ib2++){ // kill the row
					if(ib==ib2)continue;
					kill |= (7<<(3*ib2))<<(9*ir);
					kill9 |= (1<<ib2)<<(3*ir);
				}
			}
		}
		if(aigkill) TblComplexShortBox[i]=0;
		else TblComplexShortBox[i]=kill9 ^ killd;

		word wnewbr=0,wnewbrw=TblComplexShortBox[i];
		if(wnewbrw) {// see if a new minirow alone appears
			for(int j=0;j<3;j++){
				word boxkill=(7<<(3*j)) & wnewbrw;
				if(!boxkill) continue;
				word newbox= (i &  (7<<(3*j))) ^ boxkill;
				if(BitCount[newbox]==1) wnewbr |= newbox;
			}
		}
		TblNewBoxRow[i]= wnewbr;

		// mask for any killed group of minirows
		int km=0;
		for(int j=0;j<9;j++)
			if((i & (1<<j))) 		km |=( 7 << (3*j));
		TblKillMask[i]=km^BIT_SET_30;

		for(int ir=0;ir<3;ir++){ // now locked in rows 
			int iw=i & (7<<(3*ir));
			if(!BitCount[iw]) {aigkill=1;break;}
			if(BitCount[iw] == 1){
				int imini=Tblfirst0_8[iw],ib=imini%3;
				if(ctlrb & (1<<ib)) {aigkill=1;break;}
				else ctlrb |= (1<<ib);
				shsh |= (1<<imini);
				for(int ir2=0;ir2<3;ir2++){ // kill the box
					if(ir2==ir) continue;
					kill |= (7<<(3*ib))<<(9*ir2);
					kill9 |= (1<<ib)<<(3*ir2);
				}
			}
		}
		if(aigkill) { kill=0; shsh=0;}
		else kill ^=BIT_SET_30;
		//small differences with zhou table, no logic difference
		TblComplexMask[i] = kill; 
		//  find shrinksingles

		int shsing;
		if(!kill || kill==BIT_SET_30){ // shrink must be 0
			shsing=0;
		}
		else{
			shsing= kill9 ^ 0x1ff;
			if(BitCount[shsing & 7 ] - 1) shsing &= 0x1f8;
			if(BitCount[shsing & 0x38 ] - 1) shsing &= 0x1c7;
			if(BitCount[shsing & 0x1c0 ] - 1) shsing &= 0x3f;
		}
		TblShrinkSingle[i] = shsing ;

		if(aigkill) TblComplexShort[i]=0;
		else TblComplexShort[i]=kill9 ^ killd;

		
		int wcols=0;  // TblColumnSingle 
		if(BitCount[i&7] && BitCount[i&0x38] && BitCount[i&0x1c0]){
			if(BitCount[i&7] == 1) wcols |= 0x49;
			if(BitCount[i&0x38] == 1) wcols |= 0x92;
			if(BitCount[i&0x1c0] == 1) wcols |= 0x124;
		}
		TblColumnSingle[i] = wcols;

		int wru=0;  // byte TblRowUniq[512]
		if(!(i&7) ) wru |= 1;
		if(!(i&0x38)) wru |= 2;
		if(!(i&0x1c0)) wru |=4;
		TblRowUniq[i] = wru;

		int killcols=0;
		if(BitCount[i&7] == 1) killcols |= i&7;		
		if(BitCount[i&0x38] == 1) killcols |= i&0x38;  
		if(BitCount[i&0x1c0] == 1) killcols |= i&0x1c0; 
		TblColumnSingleinBox[i]=killcols;

		int killcolsf= ( killcols | (killcols<<9) | (killcols<<18))^BIT_SET_30;
		TblMaskSingle[i] = killcolsf;

		int killcols2=0;
		if(BitCount[i&7] == 2) killcols2 |= i&7;		
		if(BitCount[i&0x38] == 2) killcols2 |= i&0x38;  
		if(BitCount[i&0x1c0] == 2) killcols2 |= i&0x1c0; 
		int killcolsf2= ( killcols2 | (killcols2<<9) | (killcols2<<18))^BIT_SET_30;
		TblMaskDouble[i] = killcolsf2;
	//	if(i==1)
	//		cout<<"ctl  i="<<dec<< i << "  " <<hex<<i
	//		<<  " killcolsf " <<killcolsf<<" TblMaskSingle "<< TblMaskSingle[i] <<endl;
	}}

/* tables to speed up the process bit field to list
   first table is the list of bits for each value of a byte
   second table is an index to the first table

*/
PMBF pairinbox;
USHORT mask_mini_row[3]={7,7<<3,7<<6},
	   mask_mini_col[3]={1+8+64,73<<1,73<<2},mask_empty_holes[9];

byte tv_string[1024];
word tv_strindex[256];
void GEN_TABLES::Gen4(){
	tv_strindex[0]=0;
	int n=0;
	for(int i=1;i<256;i++){
		for(int j=0;j<9;j++)
			if(i & (1<<j))	tv_string[n++]=j;
		tv_strindex[i]=n;
	}
	pairinbox.SetAll_0();
	// prepare table for pairs in box
	UCAND tpa[]={1+16,1+32,1+128,1+256,
		          2+8,2+32,2+64,2+256,
				  4+8,4+16,4+64,4+128,
				  +128,8+256,16+64,16+256,32+64,32+128
				};
	for(int i=0;i<18;i++)
		pairinbox.SetU(tpa[i]);
	for(int i=0,ij=0;i<3;i++)for(int j=0;j<3;j++,ij++){
		mask_empty_holes[ij]=0x1ff ^ (mask_mini_row[i] | mask_mini_col[j]);
	}

}